/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/*
 * Base class for all objects used in simulation.
 * Object belongs in some world and space, it can have child objects and 
 * primitives as its parts.
 *
 * Remember to call superclass constructors when creating subclasses.
 */

#ifndef OBJECT_H
#define OBJECT_H

#include <cstdlib>
#include <string>
#include <vector>

#include "ode/ode.h"

class CWorld;
class CPrimitive;
class CObject;

typedef std::vector<CPrimitive*>::iterator PrimitivesIter;
typedef std::vector<CObject*>::iterator ObjectsIter;

class CObject
{
public:
  CWorld *SimWorld; ///< the simulation world this object belongs to
  CObject *Parent;  ///< Parent of this object
  dWorldID WorldID; ///< the ode world this object belongs to
  dSpaceID SpaceID; ///< this objects space
  dSpaceID StaticSpaceID; ///< Static objects, such as walls, here please
public:
  /**
   * Create new object.
   *
   * @param[in] World         Pointer to The World.
   * @param[in] ParentObject  Pointer to ParentObject if any, otherwise NULL.
   */
  CObject(CWorld *World, CObject *ParentObject);
    
  virtual ~CObject();
    

  /**
   * this is called (by worlds creator) once after the world is fully created
   * this allows objects to perform inits that can't be done in constructor
   */
  virtual void Activate();


  /**
   * this is called (by worlds creator) once after the world is fully created
   * this allows objects to perform inits that can't be done in constructor
   */
  virtual void Deactivate();

    
  /** 
   * This is called by the world on every simulation step.  this
   * could be used for example to update visualisation and contact
   * data
   *
   * @param[in] StepSize Last simulation step size in seconds (How
   * much 'Simulation' time has elapsed since last update)
   */
  virtual void Update(float StepSize)=0;

    
  /**
   * This is called by the world when being drawn
   */
  virtual void Draw()=0;
    

  /**
   * called by primitives in case of collision, first primitive is the calling one,
   * second the one that is being collided with (NULL if none)
   *
   * @param[in] primitive     Calling (Collided object)
   * @param[in] numc          Number of contact points in 'contacts' array.
   * @param[in] contacts      Contact points as given by ODE engine.
   * @param[in] primitive2    Object colliding with the current one.
   */
  virtual void OnCollision(CPrimitive *primitive, int numc, dContact *contacts, CPrimitive *primitive2)=0;
    

  /** 
   * Gets pointer to pointer array containing all registered children.
   */
  const std::vector<CObject*> * GetChildren();
    
protected:
    
  std::vector<CPrimitive*> Parts; ///< primitive objects that make this object
  std::vector<CObject*> Children; ///< child objects
    
private:  
};

#endif //OBJECT_H
